<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
 
<html xmlns="http://www.w3.org/1999/xhtml">

<head>
    <title>Android系统匿名共享内存Ashmem（Anonymous Shared Memory）简要介绍和学习计划 - 老罗的Android之旅
        - 博客频道 - CSDN.NET</title>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
    <meta name="description" content="在Android系统中，提供了独特的匿名共享内存子系统Ashmem（Anonymous Shared Memory），它以驱动程序的形式实现在内核空间中。它有两个特点，一是能够辅助内存管理系统来有效地管理不再使用的内存块，二是它通过Binder进程间通信机制来实现进程间的内存共享。本文中，我们将通过实例来简要介绍Android系统的匿名共享内存的使用方法，使得我们对Android系统的匿名共享内存" />
    <script src="http://static.blog.csdn.net/scripts/jquery.js" type="text/javascript"></script>
    <script type="text/javascript" src="http://static.blog.csdn.net/scripts/ad.js?v=1.1"></script>
        <!--new top-->
               <link rel="stylesheet" href="http://static.csdn.net/public/common/toolbar/css/index.css">        <!--new top-->

    <link rel="Stylesheet" type="text/css" href="http://static.blog.csdn.net/skin/default/css/style.css?v=1.1" />
    <link id="RSSLink" title="RSS" type="application/rss+xml" rel="alternate" href="/Luoshengyang/rss/list" />
    <link rel="shortcut icon" href="/favicon.ico" />
    <link type="text/css" rel="stylesheet" href="http://static.blog.csdn.net/scripts/SyntaxHighlighter/styles/default.css" />
 

</head>
<body>
    
   
      <!--new top-->
    <script id="toolbar-tpl-scriptId" fixed="true" prod="blog" skin="black" src="http://static.csdn.net/public/common/toolbar/js/html.js" type="text/javascript"></script>
     <!--new top-->
    <div id="container">
        <div id="header">
    <div class="header">
        <div id="blog_title">
            <h2>
                <a href="http://blog.csdn.net/luoshengyang">老罗的Android之旅</a></h2>
            <h3>爱生活，爱Android</h3>
            <div class="clear">
            </div>
        </div>
        <div class="clear">
        </div>
    </div>
</div>
<div id="navigator">
    <div class="navigator_bg">
    </div>
    <div class="navigator">
        <ul>
                <li id="btnContents"><a href="http://blog.csdn.net/luoshengyang?viewmode=contents"><span onclick="_gaq.push(['_trackEvent','function', 'onclick', 'blog_articles_mulu'])">
                    <img src="http://static.blog.csdn.net/images/ico_list.gif">目录视图</span></a></li>
                <li id="btnView"><a href="http://blog.csdn.net/luoshengyang?viewmode=list"><span onclick="_gaq.push(['_trackEvent','function', 'onclick', 'blog_articles_zhaiyao'])">
                    <img src="http://static.blog.csdn.net/images/ico_summary.gif">摘要视图</span></a></li>
                <li id="btnRss"><a href="http://blog.csdn.net/luoshengyang/rss/list"><span onclick="_gaq.push(['_trackEvent','function', 'onclick', 'blog_articles_RSS'])">
                    <img src="http://static.blog.csdn.net/images/ico_rss.gif">订阅</span></a></li>
</ul>
    </div>
</div>
<script type="text/javascript">
    var username = "Luoshengyang";
    var _blogger = username;
    var blog_address = "http://blog.csdn.net/luoshengyang";
    var static_host = "http://static.blog.csdn.net";
    var currentUserName = "";
</script>

        <div id="body">
            <div id="main">
                <div class="main">
<div class="notice tracking-ad" data-mod='popu_3' > 


<a href="http://bss.csdn.net/cview/reg/?project_id=804&identy_id=839" target="_blank"><font color=red>“程序人生”中国软件开发者职业生涯调查
</font></a>

&nbsp;&nbsp;&nbsp;&nbsp;


<a href="http://bbs.csdn.net/topics/390724670"target="_blank">
<font color=red>CSDN社区“三八节”特别活动</font></a>
&nbsp;&nbsp;&nbsp;&nbsp;


<a href="http://www.csdn.net/article/2014-03-06/2818653"target="_blank">
<font color=blue>开发者职业生涯调查之未来</font></a>




</div>                    <link href="http://static.blog.csdn.net/css/comment1.css" type="text/css" rel="stylesheet" />
<link href="http://static.blog.csdn.net/css/style1.css" type="text/css" rel="stylesheet" />
<div id="article_details" class="details">
    <div class="article_title">
    <span class="ico ico_type_Original"></span>
    <h1>
        <span class="link_title"><a href="/luoshengyang/article/details/6651971">
        Android系统匿名共享内存Ashmem（Anonymous Shared Memory）简要介绍和学习计划
        </a></span>
    </h1>
</div>

    <div class="article_manage">
        <span class="link_categories">
        分类：
            <a href="/Luoshengyang/article/category/838604">Android</a> 
        </span>
    <span class="link_postdate">2011-08-05 00:11</span>
    <span class="link_view" title="阅读次数">29192人阅读</span>
    <span class="link_comments" title="评论次数"><a href="#comments" onclick="_gaq.push(['_trackEvent','function', 'onclick', 'blog_articles_pinglun'])">评论</a>(25)</span>
    <span class="link_collect"><a href="javascript:void(0);" onclick="javascript:_gaq.push(['_trackEvent','function', 'onclick', 'blog_articles_shoucang']);collectArticle('Android系统匿名共享内存Ashmem（Anonymous Shared Memory）简要介绍和学习计划','6651971');return false;" title="收藏">收藏</a></span>
    <span class="link_report"><a href="#report"  onclick="javascript:_gaq.push(['_trackEvent','function', 'onclick', 'blog_articles_jubao']);report(6651971,2);return false;" title="举报">举报</a></span>
    
</div>
<div class="tag2box"><a href='http://www.csdn.net/tag/android' target=_blank onclick="_gaq.push(['_trackEvent','function', 'onclick', 'blog_articles_tag']);">android</a><a href='http://www.csdn.net/tag/descriptor' target=_blank onclick="_gaq.push(['_trackEvent','function', 'onclick', 'blog_articles_tag']);">descriptor</a><a href='http://www.csdn.net/tag/layout' target=_blank onclick="_gaq.push(['_trackEvent','function', 'onclick', 'blog_articles_tag']);">layout</a><a href='http://www.csdn.net/tag/server' target=_blank onclick="_gaq.push(['_trackEvent','function', 'onclick', 'blog_articles_tag']);">server</a><a href='http://www.csdn.net/tag/string' target=_blank onclick="_gaq.push(['_trackEvent','function', 'onclick', 'blog_articles_tag']);">string</a></div>

    
<div id="article_content" class="article_content">
<p>&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;在Android系统中，提供了独特的匿名共享内存子系统Ashmem（Anonymous Shared Memory），它以驱动程序的形式实现在内核空间中。它有两个特点，一是能够辅助内存管理系统来有效地管理不再使用的内存块，二是它通过Binder进程间通信机制来实现进程间的内存共享。本文中，我们将通过实例来简要介绍Android系统的匿名共享内存的使用方法，使得我们对Android系统的匿名共享内存机制有一个感性的认识，为进一步学习它的源代码实现打下基础。</p><p>&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;Android系统的匿名共享内存子系统的主体是以驱动程序的形式实现在内核空间的，同时，在系统运行时库层和应用程序框架层提供了访问接口，其中，在系统运行时库层提供了C/C++调用接口，而在应用程序框架层提供了Java调用接口。这里，我们将直接通过应用程序框架层提供的Java调用接口来说明匿名共享内存子系统Ashmem的使用方法，毕竟我们在Android开发应用程序时，是基于Java语言的，而实际上，应用程序框架层的Java调用接口是通过JNI方法来调用系统运行时库层的C/C++调用接口，最后进入到内核空间的Ashmem驱动程序去的。</p><p>&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;我们在这里举的例子是一个名为Ashmem的应用程序，它包含了一个Server端和一个Client端实现，其中，Server端是以Service的形式实现的，在这里Service里面，创建一个匿名共享内存文件，而Client是一个Activity，这个Activity通过Binder进程间通信机制获得前面这个Service创建的匿名共享内存文件的句柄，从而实现共享。在Android应用程序框架层，提供了一个MemoryFile接口来封装了匿名共享内存文件的创建和使用，它实现在frameworks/base/core/java/android/os/MemoryFile.java文件中。下面，我们就来看看Server端是如何通过MemoryFile类来创建匿名共享内存文件的以及Client是如何获得这个匿名共享内存文件的句柄的。</p><p>&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;在MemoryFile类中，提供了两种创建匿名共享内存的方法，我们通过MemoryFile类的构造函数来看看这两种使用方法：</p><p></p><pre code_snippet_id="134054" snippet_file_name="blog_20131230_1_4488797"  code_snippet_id="134054" snippet_file_name="blog_20131230_1_4488797" name="code" class="java">public class MemoryFile
{
	......

	/**
	* Allocates a new ashmem region. The region is initially not purgable.
	*
	* @param name optional name for the file (can be null).
	* @param length of the memory file in bytes.
	* @throws IOException if the memory file could not be created.
	*/
	public MemoryFile(String name, int length) throws IOException {
		mLength = length;
		mFD = native_open(name, length);
		mAddress = native_mmap(mFD, length, PROT_READ | PROT_WRITE);
		mOwnsRegion = true;
	}

	/**
	* Creates a reference to an existing memory file. Changes to the original file
	* will be available through this reference.
	* Calls to {@link #allowPurging(boolean)} on the returned MemoryFile will fail.
	*
	* @param fd File descriptor for an existing memory file, as returned by
	*        {@link #getFileDescriptor()}. This file descriptor will be closed
	*        by {@link #close()}.
	* @param length Length of the memory file in bytes.
	* @param mode File mode. Currently only &quot;r&quot; for read-only access is supported.
	* @throws NullPointerException if &lt;code&gt;fd&lt;/code&gt; is null.
	* @throws IOException If &lt;code&gt;fd&lt;/code&gt; does not refer to an existing memory file,
	*         or if the file mode of the existing memory file is more restrictive
	*         than &lt;code&gt;mode&lt;/code&gt;.
	*
	* @hide
	*/
	public MemoryFile(FileDescriptor fd, int length, String mode) throws IOException {
		if (fd == null) {
			throw new NullPointerException(&quot;File descriptor is null.&quot;);
		}
		if (!isMemoryFile(fd)) {
			throw new IllegalArgumentException(&quot;Not a memory file.&quot;);
		}
		mLength = length;
		mFD = fd;
		mAddress = native_mmap(mFD, length, modeToProt(mode));
		mOwnsRegion = false;
	}

	......
}</pre>&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;从注释中，我们可以看出这两个构造函数的使用方法，这里就不再详述了。两个构造函数的主要区别是第一个参数，第一种构造方法是以指定的字符串调用JNI方法native_open来创建一个匿名共享内存文件，从而得到一个文件描述符，接着就以这个文件描述符为参数调用JNI方法natvie_mmap把这个匿名共享内存文件映射在进程空间中，然后就可以通过这个映射后得到的地址空间来直接访问内存数据了；第二种构造方法是以指定的文件描述符来直接调用JNI方法natvie_mmap把这个匿名共享内存文件映射在进程空间中，然后进行访问，而这个文件描述符就必须要是一个匿名共享内存文件的文件描述符，这是通过一个内部函数isMemoryFile来验证的，而这个内部函数isMemoryFile也是通过JNI方法调用来进一步验证的。前面所提到的这些JNI方法调用，最终都是通过系统运行时库层进入到内核空间的Ashmem驱动程序中去，不过这里我们不关心这些JNI方法、系统运行库层调用以及Ashmem驱动程序的具体实现，在接下来的两篇文章中，我们将会着重介绍，这里我们只关注MemoryFile这个类的使用方法。<p></p><p>&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;前面我们说到，我们在这里举的例子包含了一个Server端和一个Client端实现，其中， Server端就是通过前面一个构造函数来创建一个匿名共享内存文件，接着，Client端过Binder进程间通信机制来向Server请求这个匿名共享内存的文件描述符，有了这个文件描述符之后，就可以通过后面一个构造函数来共享这个内存文件了。</p><p>&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;因为涉及到Binder进程间通信，我们首先定义好Binder进程间通信接口。Binder进程间通信机制的相关介绍，请参考前面一篇文章<a target=_blank target="_blank" href="http://blog.csdn.net/luoshengyang/article/details/6618363">Android进程间通信（IPC）机制Binder简要介绍和学习计划</a>，这里就不详细介绍了，直接进入主题。<br />&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;首先在源代码工程的packages/experimental目录下创建一个应用程序工程目录Ashmem。关于如何获得Android源代码工程，请参考<a target=_blank target="_blank" href="http://blog.csdn.net/luoshengyang/article/details/6559955">在Ubuntu上下载、编译和安装Android最新源代码</a>一文；关于如何在Android源代码工程中创建应用程序工程，请参考<a target=_blank target="_blank" href="http://blog.csdn.net/luoshengyang/article/details/6580267">在Ubuntu上为Android系统内置Java应用程序测试Application Frameworks层的硬件服务</a>一文。这里，工程名称就是Ashmem了，它定义了一个路径为shy.luo.ashmem的package，这个例子的源代码主要就是实现在这里了。下面，将会逐一介绍这个package里面的文件。</p><p>&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;这里要用到的Binder进程间通信接口定义在src/shy/luo/ashmem/IMemoryService.java文件中：</p><p></p><pre code_snippet_id="134054" snippet_file_name="blog_20131230_2_6408408"  code_snippet_id="134054" snippet_file_name="blog_20131230_2_6408408" name="code" class="java">package shy.luo.ashmem;

import android.util.Log;
import android.os.IInterface;
import android.os.Binder;
import android.os.IBinder;
import android.os.Parcel;
import android.os.ParcelFileDescriptor;
import android.os.RemoteException;

public interface IMemoryService extends IInterface {
	public static abstract class Stub extends Binder implements IMemoryService {
		private static final String DESCRIPTOR = &quot;shy.luo.ashmem.IMemoryService&quot;;

		public Stub() {
			attachInterface(this, DESCRIPTOR);
		}

		public static IMemoryService asInterface(IBinder obj) {
			if (obj == null) {
				return null;
			}

			IInterface iin = (IInterface)obj.queryLocalInterface(DESCRIPTOR);
			if (iin != null &amp;&amp; iin instanceof IMemoryService) {
				return (IMemoryService)iin;
			}

			return new IMemoryService.Stub.Proxy(obj);
		}

		public IBinder asBinder() {
			return this;
		}

		@Override 
		public boolean onTransact(int code, Parcel data, Parcel reply, int flags) throws android.os.RemoteException {
			switch (code) {
			case INTERFACE_TRANSACTION: {
				reply.writeString(DESCRIPTOR);
				return true;
			}
			case TRANSACTION_getFileDescriptor: {
				data.enforceInterface(DESCRIPTOR);
				
				ParcelFileDescriptor result = this.getFileDescriptor();
				
				reply.writeNoException();
				
				if (result != null) {
					reply.writeInt(1);
					result.writeToParcel(reply, 0);
				} else {
					reply.writeInt(0);
				}

				return true;
			}
			case TRANSACTION_setValue: {
				data.enforceInterface(DESCRIPTOR);
				
				int val = data.readInt();
				setValue(val);
				
				reply.writeNoException();
				
				return true;
			}
			}

			return super.onTransact(code, data, reply, flags);
		}

		private static class Proxy implements IMemoryService {
			private IBinder mRemote;

			Proxy(IBinder remote) {
				mRemote = remote;
			}

			public IBinder asBinder() {
				return mRemote;
			}

			public String getInterfaceDescriptor() {
				return DESCRIPTOR;
			}

			public ParcelFileDescriptor getFileDescriptor() throws RemoteException {
				Parcel data = Parcel.obtain();
				Parcel reply = Parcel.obtain();

				ParcelFileDescriptor result;
	
				try {
					data.writeInterfaceToken(DESCRIPTOR);

					mRemote.transact(Stub.TRANSACTION_getFileDescriptor, data, reply, 0);
		
					reply.readException();
					if (0 != reply.readInt()) {
						result = ParcelFileDescriptor.CREATOR.createFromParcel(reply);
					} else {
						result = null;
					}
				} finally {
					reply.recycle();
					data.recycle();
				}
	
				return result;
			}

			public void setValue(int val) throws RemoteException {
				Parcel data = Parcel.obtain();
				Parcel reply = Parcel.obtain();

				try {
					data.writeInterfaceToken(DESCRIPTOR);
					data.writeInt(val);

					mRemote.transact(Stub.TRANSACTION_setValue, data, reply, 0);
					
					reply.readException();
				} finally {
					reply.recycle();
					data.recycle();
				}
			}
		}

		static final int TRANSACTION_getFileDescriptor = IBinder.FIRST_CALL_TRANSACTION + 0;
		static final int TRANSACTION_setValue = IBinder.FIRST_CALL_TRANSACTION + 1;

	}

	public ParcelFileDescriptor getFileDescriptor() throws RemoteException;
	public void setValue(int val) throws RemoteException;
}</pre>&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;这里主要是定义了IMemoryService接口，它里面有两个调用接口：<p></p><p></p><pre code_snippet_id="134054" snippet_file_name="blog_20131230_3_4074876"  code_snippet_id="134054" snippet_file_name="blog_20131230_3_4074876" name="code" class="java">	public ParcelFileDescriptor getFileDescriptor() throws RemoteException;
	public void setValue(int val) throws RemoteException;</pre>&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;同时，还分别定义了用于Server端实现的IMemoryService.Stub基类和用于Client端使用的代理IMemoryService.Stub.Proxy类。关于Binder进程间通信机制在应用程序框架层的Java接口定义，请参考前面<a target=_blank target="_blank" href="http://blog.csdn.net/luoshengyang/article/details/6642463">Android系统进程间通信Binder机制在应用程序框架层的Java接口源代码分析</a>一文。<p></p><p>&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;有了Binder进程间通信接口之后，接下来就是要在Server端实现一个本地服务了。这里，Server端实现的本地服务名为MemoryService，实现在src/shy/luo/ashmem/MemoryService.java文件中：</p><p></p><pre code_snippet_id="134054" snippet_file_name="blog_20131230_4_5852783"  code_snippet_id="134054" snippet_file_name="blog_20131230_4_5852783" name="code" class="java">package shy.luo.ashmem;

import java.io.FileDescriptor;
import java.io.IOException;

import android.os.Parcel;
import android.os.MemoryFile;
import android.os.ParcelFileDescriptor;
import android.util.Log;

public class MemoryService extends IMemoryService.Stub {
	private final static String LOG_TAG = &quot;shy.luo.ashmem.MemoryService&quot;;
	private MemoryFile file = null;
	
	public MemoryService() {
		try {
                        file = new MemoryFile(&quot;Ashmem&quot;, 4);
                        setValue(0);
                }
                catch(IOException ex) {
                        Log.i(LOG_TAG, &quot;Failed to create memory file.&quot;);
                        ex.printStackTrace();
                }
	}

	public ParcelFileDescriptor getFileDescriptor() {
		Log.i(LOG_TAG, &quot;Get File Descriptor.&quot;);

		ParcelFileDescriptor pfd = null;

		try {
			pfd = file.getParcelFileDescriptor();
		} catch(IOException ex) {
			Log.i(LOG_TAG, &quot;Failed to get file descriptor.&quot;);
			ex.printStackTrace();
		}

		return pfd;
	}
	
	public void setValue(int val) {
		if(file == null) {
			return;
		}

		byte[] buffer = new byte[4];   
		buffer[0] = (byte)((val &gt;&gt;&gt; 24) &amp; 0xFF);
		buffer[1] = (byte)((val &gt;&gt;&gt; 16) &amp; 0xFF);
		buffer[2] = (byte)((val &gt;&gt;&gt; 8) &amp; 0xFF); 
		buffer[3] = (byte)(val &amp; 0xFF);
		
		try {
			file.writeBytes(buffer, 0, 0, 4);
			Log.i(LOG_TAG, &quot;Set value &quot; + val + &quot; to memory file. &quot;);
		}
		catch(IOException ex) {
			Log.i(LOG_TAG, &quot;Failed to write bytes to memory file.&quot;);
			ex.printStackTrace();
		}
	}
}</pre>&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;注意，这里的MemoryService类实现了IMemoryService.Stub类，表示这是一个Binder服务的本地实现。在构造函数中，通过指定文件名和文件大小来创建了一个匿名共享内存文件，即创建MemoryFile的一个实例，并保存在类成员变量file中。这个匿名共享内存文件名为&quot;Ashmem&quot;，大小为4个节字，刚好容纳一个整数，我们这里举的例子就是要说明如果创建一个匿名共享内存来在两个进程间实现共享一个整数了。当然，在实际应用中，可以根据需要创建合适大小的共享内存来共享有意义的数据。<p></p><p>&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;这里还实现了IMemoryService.Stub的两个接口getFileDescriptor和setVal，一个用来获取匿名共享内存文件的文件描述符，一个来往匿名共享内存文件中写入一个整数，其中，接口getFileDescriptor的返回值是一个ParcelFileDescriptor。在Java中，是用FileDescriptor类来表示一个文件描述符的，而ParcelFileDescriptor是用来序列化FileDescriptor的，以便在进程间调用时传输。<br />&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;定义好本地服务好，就要定义一个Server来启动这个服务了。这里定义的Server实现在src/shy/luo/ashmem/Server.java文件中：</p><p></p><pre code_snippet_id="134054" snippet_file_name="blog_20131230_5_1883049"  code_snippet_id="134054" snippet_file_name="blog_20131230_5_1883049" name="code" class="java">package shy.luo.ashmem;

import android.app.Service;
import android.content.Intent;
import android.os.IBinder;
import android.util.Log;
import android.os.ServiceManager;

public class Server extends Service {
    private final static String LOG_TAG = &quot;shy.luo.ashmem.Server&quot;;

    private MemoryService memoryService = null;

    @Override
    public IBinder onBind(Intent intent) {
        return null;
    }

    @Override
    public void onCreate() {
	Log.i(LOG_TAG, &quot;Create Memory Service...&quot;);

	memoryService = new MemoryService();

        try {
            ServiceManager.addService(&quot;AnonymousSharedMemory&quot;, memoryService);
            Log.i(LOG_TAG, &quot;Succeed to add memory service.&quot;);
        } catch (RuntimeException ex) {
            Log.i(LOG_TAG, &quot;Failed to add Memory Service.&quot;);
            ex.printStackTrace();
        }

    }

    @Override
    public void onStart(Intent intent, int startId) {
        Log.i(LOG_TAG, &quot;Start Memory Service.&quot;);
    }

    @Override
    public void onDestroy() {
	Log.i(LOG_TAG, &quot;Destroy Memory Service.&quot;);
    }
}</pre>&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;这个Server继承了Android系统应用程序框架层提供的Service类，当它被启动时，运行在一个独立的进程中。当这个Server被启动时，它的onCreate函数就会被调用，然后它就通过ServiceManager的addService接口来添加MemoryService了：<p></p><p></p><pre code_snippet_id="134054" snippet_file_name="blog_20131230_6_1152701"  code_snippet_id="134054" snippet_file_name="blog_20131230_6_1152701" name="code" class="java">    memoryService = new MemoryService();

    try {
        ServiceManager.addService(&quot;AnonymousSharedMemory&quot;, memoryService);
        Log.i(LOG_TAG, &quot;Succeed to add memory service.&quot;);
    } catch (RuntimeException ex) {
        Log.i(LOG_TAG, &quot;Failed to add Memory Service.&quot;);
        ex.printStackTrace();
    }</pre>&nbsp;&nbsp; &nbsp; &nbsp; 这样，当这个Server成功启动了，Client就可以通过ServiceManager的getService接口来获取这个MemoryService了。<p></p><p>&nbsp;&nbsp; &nbsp; &nbsp; 接着，我们就来看Client端的实现。Client端是一个Activity，实现在src/shy/luo/ashmem/Client.java文件中：</p><p></p><pre code_snippet_id="134054" snippet_file_name="blog_20131230_7_4326047"  code_snippet_id="134054" snippet_file_name="blog_20131230_7_4326047" name="code" class="java">package shy.luo.ashmem;

import java.io.FileDescriptor;
import java.io.IOException;

import shy.luo.ashmem.R;
import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.os.MemoryFile;
import android.os.ParcelFileDescriptor;
import android.os.ServiceManager;
import android.os.RemoteException;
import android.util.Log;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.EditText;

public class Client extends Activity implements OnClickListener {
	private final static String LOG_TAG = &quot;shy.luo.ashmem.Client&quot;;
	
	IMemoryService memoryService = null;
	MemoryFile memoryFile = null;
	
	private EditText valueText = null;
	private Button readButton = null;
	private Button writeButton = null;
	private Button clearButton = null;
	
    	@Override
    	public void onCreate(Bundle savedInstanceState) {
        	super.onCreate(savedInstanceState);
        	setContentView(R.layout.main);

		IMemoryService ms = getMemoryService();
		if(ms == null) {        
        		startService(new Intent(&quot;shy.luo.ashmem.server&quot;));
		} else {
			Log.i(LOG_TAG, &quot;Memory Service has started.&quot;);
		}

        	valueText = (EditText)findViewById(R.id.edit_value);
        	readButton = (Button)findViewById(R.id.button_read);
        	writeButton = (Button)findViewById(R.id.button_write);
        	clearButton = (Button)findViewById(R.id.button_clear);

		readButton.setOnClickListener(this);
        	writeButton.setOnClickListener(this);
        	clearButton.setOnClickListener(this);
        
        	Log.i(LOG_TAG, &quot;Client Activity Created.&quot;);
    	}

    	@Override
    	public void onResume() {
		super.onResume();

		Log.i(LOG_TAG, &quot;Client Activity Resumed.&quot;);
    	}

    	@Override
    	public void onPause() {
		super.onPause();

		Log.i(LOG_TAG, &quot;Client Activity Paused.&quot;);
    	}
    
    	@Override
    	public void onClick(View v) {
    		if(v.equals(readButton)) {
    			int val = 0;
    		
    			MemoryFile mf = getMemoryFile();
    			if(mf != null) {
				try {
    					byte[] buffer = new byte[4];
    					mf.readBytes(buffer, 0, 0, 4);
    			
    					val = (buffer[0] &lt;&lt; 24) | ((buffer[1] &amp; 0xFF) &lt;&lt; 16) | ((buffer[2] &amp; 0xFF) &lt;&lt; 8) | (buffer[3] &amp; 0xFF);
				} catch(IOException ex) {
					Log.i(LOG_TAG, &quot;Failed to read bytes from memory file.&quot;);
					ex.printStackTrace();
				}
    			}	
    		
    			String text = String.valueOf(val);
    			valueText.setText(text);
    		} else if(v.equals(writeButton)) {
    			String text = valueText.getText().toString();
    			int val = Integer.parseInt(text);
    		
    			IMemoryService ms = getMemoryService();
    			if(ms != null) {
				try {
    					ms.setValue(val);
				} catch(RemoteException ex) {
					Log.i(LOG_TAG, &quot;Failed to set value to memory service.&quot;);
					ex.printStackTrace();
				}
    			}
    		} else if(v.equals(clearButton)) {
    			String text = &quot;&quot;;
    			valueText.setText(text);
    		}
    	}
    
    	private IMemoryService getMemoryService() {
    		if(memoryService != null) {
    			return memoryService;
    		}
    	
    		memoryService = IMemoryService.Stub.asInterface(
                			ServiceManager.getService(&quot;AnonymousSharedMemory&quot;));

		Log.i(LOG_TAG, memoryService != null ? &quot;Succeed to get memeory service.&quot; : &quot;Failed to get memory service.&quot;);
    	
    		return memoryService;
    	}
    
    	private MemoryFile getMemoryFile() {
    		if(memoryFile != null) {
    			return memoryFile;
    		}
    		
    		IMemoryService ms = getMemoryService();
    		if(ms != null) {
			try {
    				ParcelFileDescriptor pfd = ms.getFileDescriptor();
				if(pfd == null) {
					Log.i(LOG_TAG, &quot;Failed to get memory file descriptor.&quot;);
					return null;
				}

				try {
					FileDescriptor fd = pfd.getFileDescriptor();
					if(fd == null) {
						Log.i(LOG_TAG, &quot;Failed to get memeory file descriptor.&quot;);
						return null;                      
					}	

    					memoryFile = new MemoryFile(fd, 4, &quot;r&quot;);
				} catch(IOException ex) {
					Log.i(LOG_TAG, &quot;Failed to create memory file.&quot;);
					ex.printStackTrace();
				}
    			} catch(RemoteException ex) {
				Log.i(LOG_TAG, &quot;Failed to get file descriptor from memory service.&quot;);
				ex.printStackTrace();
			}
		}
    	
    		return memoryFile;
    	}
}</pre>&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;Client端的界面主要包含了三个按钮Read、Write和Clear，以及一个用于显示内容的文本框。<p></p><p>&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;这个Activity在onCreate时，会通过startService接口来启动我们前面定义的Server进程。调用startService时，需要指定要启动的服务的名称，这里就是&quot;shy.luo.ashmem.server&quot;了，后面我们会在程序的描述文件AndroidManifest.xml看到前面的Server类是如何和名称&quot;shy.luo.ashmem.server&quot;关联起来的。关于调用startService函数来启动自定义服务的过程，可以参考<a target=_blank target="_blank" href="http://blog.csdn.net/luoshengyang/article/details/6677029">Android系统在新进程中启动自定义服务过程（startService）的原理分析</a>一文。</p><p>&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;内部函数getMemoryService用来获取IMemoryService。如果是第一次调用该函数，则会通过ServiceManager的getService接口来获得这个IMemoryService接口，然后保存在类成员变量memoryService中，以后再调用这个函数时，就可以直接返回memoryService了。</p><p>&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;内部函数getMemoryFile用来从MemoryService中获得匿名共享内存文件的描述符。同样，如果是第一次调用该函数，则会通过IMemoryService的getFileDescriptor接口来获得MemoryService中的匿名共享内存文件的描述符，然后用这个文件描述符来创建一个MemoryFile实例，并保存在类成员变量memoryFile中，以后再调用这个函数时，就可以直接返回memoryFile了。</p><p>&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;有了memoryService和memoryFile后，我们就可以在Client端访问Server端创建的匿名共享内存了。点击Read按钮时，就通过memoryFile的readBytes接口把共享内存中的整数读出来，并显示在文本框中；点击Write按钮时，就通过memoryService这个代理类的setVal接口来调用MemoryService的本地实现类的setVal服务，从而把文本框中的数值写到Server端创建的匿名共享内存中去；点击Clear按钮时，就会清空文本框的内容。这样，我们就可以通过Read和Write按钮来验证我们是否在Client和Server两个进程中实现内存共享了。</p><p>&nbsp;&nbsp; &nbsp; &nbsp; 现在，我们再来看看Client界面的配置文件，它定义在res/layout/main.xml文件中：</p><p></p><pre code_snippet_id="134054" snippet_file_name="blog_20131230_8_4675494"  code_snippet_id="134054" snippet_file_name="blog_20131230_8_4675494" name="code" class="html">&lt;?xml version=&quot;1.0&quot; encoding=&quot;utf-8&quot;?&gt;
&lt;LinearLayout xmlns:android=&quot;http://schemas.android.com/apk/res/android&quot;
    android:orientation=&quot;vertical&quot;
    android:layout_width=&quot;fill_parent&quot;
    android:layout_height=&quot;fill_parent&quot;
    &gt;
    &lt;LinearLayout
    	android:layout_width=&quot;fill_parent&quot;
    	android:layout_height=&quot;wrap_content&quot;
    	android:orientation=&quot;vertical&quot; 
    	android:gravity=&quot;center&quot;&gt;
    	&lt;TextView 
			android:layout_width=&quot;wrap_content&quot;
       		android:layout_height=&quot;wrap_content&quot; 
        	android:text=&quot;@string/value&quot;&gt;
    	&lt;/TextView&gt;
    	&lt;EditText 
     		android:layout_width=&quot;fill_parent&quot;
        	android:layout_height=&quot;wrap_content&quot; 
        	android:id=&quot;@+id/edit_value&quot;
        	android:hint=&quot;@string/hint&quot;&gt;
    	&lt;/EditText&gt;
    &lt;/LinearLayout&gt;
     &lt;LinearLayout
    	android:layout_width=&quot;fill_parent&quot;
    	android:layout_height=&quot;wrap_content&quot;
    	android:orientation=&quot;horizontal&quot; 
    	android:gravity=&quot;center&quot;&gt;
    	&lt;Button 
    		android:id=&quot;@+id/button_read&quot;
    		android:layout_width=&quot;wrap_content&quot;
    		android:layout_height=&quot;wrap_content&quot;
    		android:text=&quot;@string/read&quot;&gt;
    	&lt;/Button&gt;
    	&lt;Button 
    		android:id=&quot;@+id/button_write&quot;
    		android:layout_width=&quot;wrap_content&quot;
    		android:layout_height=&quot;wrap_content&quot;
    		android:text=&quot;@string/write&quot;&gt;
    	&lt;/Button&gt;
    	&lt;Button 
    		android:id=&quot;@+id/button_clear&quot;
    		android:layout_width=&quot;wrap_content&quot;
    		android:layout_height=&quot;wrap_content&quot;
    		android:text=&quot;@string/clear&quot;&gt;
    	&lt;/Button&gt;
    &lt;/LinearLayout&gt;
&lt;/LinearLayout&gt;</pre>&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;相关的字符串定义在res/values/strings.xml文件中：<p></p><p></p><pre code_snippet_id="134054" snippet_file_name="blog_20131230_9_9277300"  code_snippet_id="134054" snippet_file_name="blog_20131230_9_9277300" name="code" class="html">&lt;?xml version=&quot;1.0&quot; encoding=&quot;utf-8&quot;?&gt;
&lt;resources&gt;
	&lt;string name=&quot;app_name&quot;&gt;Ashmem&lt;/string&gt;
    &lt;string name=&quot;value&quot;&gt;Value&lt;/string&gt;
    &lt;string name=&quot;hint&quot;&gt;Please input a value...&lt;/string&gt;
    &lt;string name=&quot;read&quot;&gt;Read&lt;/string&gt;
    &lt;string name=&quot;write&quot;&gt;Write&lt;/string&gt;
    &lt;string name=&quot;clear&quot;&gt;Clear&lt;/string&gt;
&lt;/resources&gt;</pre>&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;这样，界面的相关配置文件就介绍完了。<p></p><p>&nbsp;&nbsp; &nbsp; &nbsp; 我们还要再来看程序描述文件AndroidManifest.xml的相关配置，它位于Ashmem目录下：<br /></p><pre code_snippet_id="134054" snippet_file_name="blog_20131230_10_3879107"  code_snippet_id="134054" snippet_file_name="blog_20131230_10_3879107" name="code" class="html">&lt;?xml version=&quot;1.0&quot; encoding=&quot;utf-8&quot;?&gt;
&lt;manifest xmlns:android=&quot;http://schemas.android.com/apk/res/android&quot;
      package=&quot;shy.luo.ashmem&quot;
      android:sharedUserId=&quot;android.uid.system&quot;
      android:versionCode=&quot;1&quot;
      android:versionName=&quot;1.0&quot;&gt;
    &lt;application android:icon=&quot;@drawable/icon&quot; android:label=&quot;@string/app_name&quot;&gt;
        &lt;activity android:name=&quot;.Client&quot;
                  android:label=&quot;@string/app_name&quot;&gt;
            &lt;intent-filter&gt;
                &lt;action android:name=&quot;android.intent.action.MAIN&quot; /&gt;
                &lt;category android:name=&quot;android.intent.category.LAUNCHER&quot; /&gt;
            &lt;/intent-filter&gt;
        &lt;/activity&gt;
		&lt;service 
			android:enabled=&quot;true&quot; 
			android:name=&quot;.Server&quot;
			android:process=&quot;.Server&quot; &gt;
			&lt;intent-filter&gt;
                &lt;action android:name=&quot;shy.luo.ashmem.server&quot;/&gt;
                &lt;category android:name=&quot;android.intent.category.DEFAULT&quot;/&gt;
            &lt;/intent-filter&gt;
		&lt;/service&gt;
    &lt;/application&gt;
&lt;/manifest&gt;</pre>&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;这里我们可以看到，下面的配置项把服务名称&quot;shy.luo.ashmem.server&quot;和本地服务类Server关联了起来：<p></p><p></p><pre code_snippet_id="134054" snippet_file_name="blog_20131230_11_5657013"  code_snippet_id="134054" snippet_file_name="blog_20131230_11_5657013" name="code" class="html">    &lt;service 
	android:enabled=&quot;true&quot; 
	android:name=&quot;.Server&quot;
	android:process=&quot;.Server&quot; &gt;
	&lt;intent-filter&gt;
             &lt;action android:name=&quot;shy.luo.ashmem.server&quot;/&gt;
             &lt;category android:name=&quot;android.intent.category.DEFAULT&quot;/&gt;
        &lt;/intent-filter&gt;
    &lt;/service&gt;</pre>&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;这样，我们就可以通过startService(new Intent(&quot;shy.luo.ashmem.server&quot;))来启动这个Server了。不过，在Android中，启动服务是需要权限的，所以，下面这一行配置获取了启动服务需要的相应权限：<p></p><p></p><pre code_snippet_id="134054" snippet_file_name="blog_20131230_12_466563"  code_snippet_id="134054" snippet_file_name="blog_20131230_12_466563" name="code" class="html">    android:sharedUserId=&quot;android.uid.system&quot;</pre>&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;最后，我们来看工程的编译脚本文件Android.mk，它位于Ashmem目录下：<br /><pre code_snippet_id="134054" snippet_file_name="blog_20131230_13_7020216"  code_snippet_id="134054" snippet_file_name="blog_20131230_13_7020216" name="code" class="html">LOCAL_PATH:= $(call my-dir)
include $(CLEAR_VARS)

LOCAL_MODULE_TAGS := optional

LOCAL_SRC_FILES += $(call all-subdir-java-files)

LOCAL_PACKAGE_NAME := Ashmem

LOCAL_CERTIFICATE := platform

include $(BUILD_PACKAGE)</pre>&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;这里又有一个关键的地方：<p></p><p></p><pre code_snippet_id="134054" snippet_file_name="blog_20131230_14_2701818"  code_snippet_id="134054" snippet_file_name="blog_20131230_14_2701818" name="code" class="html">LOCAL_CERTIFICATE := platform</pre>&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;因为我们需要在程序中启动Service，所以要配置这一行，并且要把源代码工程放在Android源代码平台中进行编译。<p></p><p>&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;这样，整个例子的源代码实现就介绍完了，接下来就要编译了。有关如何单独编译Android源代码工程的模块，以及如何打包system.img，请参考<a target=_blank target="_blank" href="http://blog.csdn.net/luoshengyang/article/details/6566662">如何单独编译Android源代码中的模块</a>一文。<br /></p><p>&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;执行以下命令进行编译和打包：</p><p></p><pre code_snippet_id="134054" snippet_file_name="blog_20131230_15_6987979"  code_snippet_id="134054" snippet_file_name="blog_20131230_15_6987979" name="code" class="html">USER-NAME@MACHINE-NAME:~/Android$ mmm packages/experimental/Ashmem
USER-NAME@MACHINE-NAME:~/Android$ make snod</pre>&nbsp;&nbsp; &nbsp; &nbsp; 这样，打包好的Android系统镜像文件system.img就包含我们前面创建的Ashmem应用程序了。<p></p><p>&nbsp;&nbsp; &nbsp; &nbsp; 再接下来，就是运行模拟器来运行我们的例子了。关于如何在Android源代码工程中运行模拟器，请参考<a target=_blank target="_blank" href="http://blog.csdn.net/luoshengyang/article/details/6559955">在Ubuntu上下载、编译和安装Android最新源代码</a>一文。</p><p>&nbsp;&nbsp; &nbsp; &nbsp; 执行以下命令启动模拟器：</p><p></p><pre code_snippet_id="134054" snippet_file_name="blog_20131230_16_5177836"  code_snippet_id="134054" snippet_file_name="blog_20131230_16_5177836" name="code" class="html">USER-NAME@MACHINE-NAME:~/Android$ emulator</pre>&nbsp;&nbsp; &nbsp; &nbsp; 模拟器启动起，就可以在Home Screen上看到Ashmem应用程序图标了：<p></p><p><img width="700" height="498" src="http://hi.csdn.net/attachment/201108/4/0_1312473135XK3h.gif" alt="" /><br /></p><p>&nbsp;&nbsp; &nbsp; &nbsp; 点击Ashmem图标，启动Ashmem应用程序，界面如下：</p><p><img width="700" height="498" src="http://hi.csdn.net/attachment/201108/4/0_13124731984dCg.gif" alt="" /><br /></p><p>&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;这样，我们就可以验证程序的功能了，看看是否实现了在两个进程中通过使用Android系统的匿名共享内存机制来共享内存数据的功能。</p><p>&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;通过这个例子的学习，相信读者对Android系统匿名共享内存子系统Ashmem有了一个大概的认识，但是，这种认识还是停留在表面上。我们在文章开始时就提到，Android系统匿名共享内存子系统Ashmem两个特点，一是能够辅助内存管理系统来有效地管理不再使用的内存块，二是它通过Binder进程间通信机制来实现进程间的内存共享。第二个特点我们在上面这个例子中看到了，但是似乎还不够深入，我们知道，在Linux系统中，文件描述符其实就是一个整数，它是用来索引进程保存在内核空间的打开文件数据结构的，而且，这个文件描述符只是在进程内有效，也就是说，在不同的进程中，相同的文件描述符的值，代表的可能是不同的打开文件，既然是这样，把Server进程中的文件描述符传给Client进程，似乎就没有用了，但是不用担心，在传输过程中，Binder驱动程序会帮我们处理好一切，保证Client进程拿到的文件描述符是在本进程中有效的，并且它指向就是Server进程创建的匿名共享内存文件。至于第一个特点，我们也准备在后续学习Android系统匿名共享内存子系统Ashmem时，再详细介绍。</p><p>&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;因此，为了深入了解Android系统匿名共享内存子系统Ashmem，在接下来的两篇文章中，围绕上面提到的两个特点，分别学习：</p><p>&nbsp;&nbsp; &nbsp; &nbsp; 1. <a target=_blank target="_blank" href="http://blog.csdn.net/luoshengyang/article/details/6664554">Android系统匿名共享内存子系统Ashmem是如何够辅助内存管理系统来有效地管理不再使用的内存块的？</a></p><p>&nbsp;&nbsp; &nbsp; &nbsp; 2.&nbsp;<a target=_blank target="_blank" href="http://blog.csdn.net/luoshengyang/article/details/6666491">Android系统匿名共享内存子系统Ashmem是如何通过Binder进程间通信机制来实现进程间的内存共享的？</a></p><p>&nbsp;&nbsp; &nbsp; &nbsp; 学习完这两篇文章后，相信大家对&nbsp;Android系统匿名共享内存子系统Ashmem就会有一个更深刻的认识了，敬请关注。</p><p style="text-align: center;"><span style="font-size:14px;color:#cc0000;"><strong>老罗的新浪微博：<a target=_blank target="_blank" href="http://weibo.com/shengyangluo">http://weibo.com/shengyangluo</a>，欢迎关注！</strong></span><br /></p>
</div>



<!-- Baidu Button BEGIN -->
<div id="bdshare" class="bdshare_t bds_tools get-codes-bdshare" style="float: right;">
<a class="bds_qzone"></a>
<a class="bds_tsina"></a>
<a class="bds_tqq"></a>
<a class="bds_renren"></a>
<a class="bds_t163"></a>
<span class="bds_more">更多</span>
<a class="shareCount"></a>
</div>
<!-- Baidu Button END -->


<!--192.168.100.34-->
<div class="article_next_prev">
            <li class="prev_article"><span>上一篇：</span><a href="/luoshengyang/article/details/6642463" onclick="_gaq.push(['_trackEvent','function', 'onclick', 'blog_articles_shangyipian'])">Android系统进程间通信Binder机制在应用程序框架层的Java接口源代码分析</a></li>
            <li class="next_article"><span>下一篇：</span><a href="/luoshengyang/article/details/6664554" onclick="_gaq.push(['_trackEvent','function', 'onclick', 'blog_articles_xiayipian'])">Android系统匿名共享内存Ashmem（Anonymous Shared Memory）驱动程序源代码分析</a></li>
</div>

<!-- Baidu Button BEGIN -->
<script type="text/javascript" id="bdshare_js" data="type=tools&amp;uid=1536434" ></script>
<script type="text/javascript" id="bdshell_js"></script>
<script type="text/javascript">
    document.getElementById("bdshell_js").src = "http://bdimg.share.baidu.com/static/js/shell_v2.js?cdnversion=" + Math.ceil(new Date()/3600000)
</script>
<!-- Baidu Button END -->

        <div id="digg" ArticleId="6651971">
            <dl id="btnDigg" class="digg digg_disable">
                <dt onclick="_gaq.push(['_trackEvent','function', 'onclick', 'blog_articles_ding'])">顶</dt>
                <dd>13</dd>
            </dl>
            <dl id="btnBury" class="digg digg_disable">
                <dt onclick="_gaq.push(['_trackEvent','function', 'onclick', 'blog_articles_cai'])">踩</dt>
                <dd>4</dd>
            </dl>
        </div>
</div>
      <dl class="blog-associat-tag">
        <dt>相关主题推荐</dt>
        <dd>
                <a href="http://www.csdn.net/tag/内存" target="_blank">内存</a> 
                <a href="http://www.csdn.net/tag/android开发" target="_blank">android开发</a> 
                <a href="http://www.csdn.net/tag/android应用" target="_blank">android应用</a> 
                <a href="http://www.csdn.net/tag/内存管理" target="_blank">内存管理</a> 
                <a href="http://www.csdn.net/tag/数据结构" target="_blank">数据结构</a> 
        </dd>
    </dl> 
    <dl class="blog-ass-articl">
        <dt>相关博文推荐</dt>
            <dd>
                <a href="http://blog.csdn.net/u010800530/article/details/21110915" title="【贪心算法】独木舟上的旅行" target="_blank">【贪心算法】独木舟上的旅行</a></dd>
            <dd>
                <a href="http://blog.csdn.net/zhrmghl/article/details/21109937" title="h3c 6604X、7506E、5120EI的OID值" target="_blank">h3c 6604X、7506E、5120...</a></dd>
            <dd>
                <a href="http://blog.csdn.net/u010153219/article/details/21110065" title="C语言字节对齐" target="_blank">C语言字节对齐</a></dd>
            <dd>
                <a href="http://blog.csdn.net/linger2012liu/article/details/21104341" title="cuda：在GPU内存中生成带有指针的结构体" target="_blank">cuda：在GPU内存中生成带有指针的结...</a></dd>
            <dd>
                <a href="http://blog.csdn.net/mlj1668956679/article/details/21102973" title="ListActivity" target="_blank">ListActivity</a></dd>
            <dd>
                <a href="http://blog.csdn.net/hzh_0000/article/details/21095723" title="poj 2886 线段树" target="_blank">poj 2886 线段树</a></dd>
            <dd>
                <a href="http://blog.csdn.net/Green_shing/article/details/21078993" title="ANDROID垃圾回收器机制和强引用、软引用、弱引用、虚引用" target="_blank">ANDROID垃圾回收器机制和强引用、软...</a></dd>
            <dd>
                <a href="http://blog.csdn.net/Jiangweihll/article/details/21084513" title="【和你谈谈C系列之三】C语言的内存分配" target="_blank">【和你谈谈C系列之三】C语言的内存分配</a></dd>
    </dl>

    <div id="ad_cen">
        <script type="text/javascript">            BAIDU_CLB_SLOT_ID = "117306";</script>
        <script type="text/javascript" src="http://cbjs.baidu.com/js/o.js"></script>
    </div>
    <script type="text/javascript">
        //new Ad(4, 'ad_cen');
    </script>
<div id="comment_title" class="panel_head">
    查看评论<a name="comments"></a></div>
<div id="comment_list">
</div>
<div id="comment_bar">
</div>
<div id="comment_form">
</div>
<div class="announce">
    * 以上用户言论只代表其个人观点，不代表CSDN网站的观点或立场<a name="reply"></a><a name="quote"></a></div>
<script type="text/javascript">
    var fileName = '6651971';
    var commentscount = 25;
    var islock = false
</script>
<script type="text/javascript" src="http://static.blog.csdn.net/scripts/comment.js"></script>
    <div id="ad_bot">
    </div>
    <script type="text/javascript">
    new Ad(5, 'ad_bot');
    </script>
<div id="report_dialog">
</div>
<div id="d-top" style="display: none;">
    <a id="d-top-a" href="#" title="回到顶部" onclick="_gaq.push(['_trackEvent','function', 'onclick', 'blog_articles_huidaodingbu'])">
        <img src="http://static.blog.csdn.net/images/top.png" alt="TOP" /></a>
</div>
<script type="text/javascript">
    $(function ()
    {
        var d_top = $('#d-top');
        document.onscroll = function ()
        {
            var scrTop = (document.body.scrollTop || document.documentElement.scrollTop);
            if (scrTop > 500)
            {
                d_top.show();
            } else
            {
                d_top.hide();
            }
        }
        $('#d-top-a').click(function ()
        {
            scrollTo(0, 0);
            this.blur();
            return false;
        });
    });
  
</script>
<style type="text/css">
    .tag_list
    {
        background: none repeat scroll 0 0 #FFFFFF;
        border: 1px solid #D7CBC1;
        color: #000000;
        font-size: 12px;
        line-height: 20px;
        list-style: none outside none;
        margin: 10px 2% 0 1%;
        padding: 1px;
    }
    .tag_list h5
    {
        background: none repeat scroll 0 0 #E0DBD3;
        color: #47381C;
        font-size: 12px;
        height: 24px;
        line-height: 24px;
        padding: 0 5px;
        margin: 0;
    }
    .tag_list h5 a
    {
        color: #47381C;
    }
    .classify
    {
        margin: 10px 0;
        padding: 4px 12px 8px;
    }
    .classify a
    {
        margin-right: 20px;
        white-space: nowrap;
    }
</style>
<div class="tag_list">
    <h5>
        <a href="http://www.csdn.net/tag/" target="_blank">核心技术类目</a></h5>
    <div class="classify">
<a title="全部主题" href="http://www.csdn.net/tag" target="_blank" onclick="LogClickCount(this,336);">全部主题</a>
<a title="Java" href="http://www.csdn.net/tag/Java" target="_blank" onclick="LogClickCount(this,336);">Java</a>
<a title="VPN" href="http://www.csdn.net/tag/vpn" target="_blank" onclick="LogClickCount(this,336);">VPN</a>
<a title="Android" href="http://www.csdn.net/tag/android" target="_blank" onclick="LogClickCount(this,336);">Android</a>
<a title="iOS" href="http://www.csdn.net/tag/ios" target="_blank" onclick="LogClickCount(this,336);">iOS</a>
<a title="ERP" href="http://www.csdn.net/tag/erp" target="_blank" onclick="LogClickCount(this,336);">ERP</a>
<a title="IE10" href="http://www.csdn.net/tag/ie10" target="_blank" onclick="LogClickCount(this,336);">IE10</a>
<a title="Eclipse" href="http://www.csdn.net/tag/eclipse" target="_blank" onclick="LogClickCount(this,336);">Eclipse</a>
<a title="CRM" href="http://www.csdn.net/tag/crm" target="_blank" onclick="LogClickCount(this,336);">CRM</a>
<a title="JavaScript" href="http://www.csdn.net/tag/javascript" target="_blank" onclick="LogClickCount(this,336);">JavaScript</a>
<a title="Ubuntu" href="http://www.csdn.net/tag/ubuntu" target="_blank" onclick="LogClickCount(this,336);">Ubuntu</a>
<a title="NFC" href="http://www.csdn.net/tag/nfc" target="_blank" onclick="LogClickCount(this,336);">NFC</a>
<a title="WAP" href="http://www.csdn.net/tag/wap" target="_blank" onclick="LogClickCount(this,336);">WAP</a>
<a title="jQuery" href="http://www.csdn.net/tag/jquery" target="_blank" onclick="LogClickCount(this,336);">jQuery</a>
<a title="数据库" href="http://www.csdn.net/tag/数据库" target="_blank" onclick="LogClickCount(this,336);">数据库</a>
<a title="BI" href="http://www.csdn.net/tag/bi" target="_blank" onclick="LogClickCount(this,336);">BI</a>
<a title="HTML5" href="http://www.csdn.net/tag/html5" target="_blank" onclick="LogClickCount(this,336);">HTML5</a>
<a title="Spring" href="http://www.csdn.net/tag/spring" target="_blank" onclick="LogClickCount(this,336);">Spring</a>
<a title="Apache" href="http://www.csdn.net/tag/apache" target="_blank" onclick="LogClickCount(this,336);">Apache</a>
<a title="Hadoop" href="http://www.csdn.net/tag/hadoop" target="_blank" onclick="LogClickCount(this,336);">Hadoop</a>
<a title=".NET" href="http://www.csdn.net/tag/.net" target="_blank" onclick="LogClickCount(this,336);">.NET</a>
<a title="API" href="http://www.csdn.net/tag/api" target="_blank" onclick="LogClickCount(this,336);">API</a>
<a title="HTML" href="http://www.csdn.net/tag/html" target="_blank" onclick="LogClickCount(this,336);">HTML</a>
<a title="SDK" href="http://www.csdn.net/tag/sdk" target="_blank" onclick="LogClickCount(this,336);">SDK</a>
<a title="IIS" href="http://www.csdn.net/tag/iis" target="_blank" onclick="LogClickCount(this,336);">IIS</a>
<a title="Fedora" href="http://www.csdn.net/tag/fedora" target="_blank" onclick="LogClickCount(this,336);">Fedora</a>
<a title="XML" href="http://www.csdn.net/tag/xml" target="_blank" onclick="LogClickCount(this,336);">XML</a>
<a title="LBS" href="http://www.csdn.net/tag/lbs" target="_blank" onclick="LogClickCount(this,336);">LBS</a>
<a title="Unity" href="http://www.csdn.net/tag/unity" target="_blank" onclick="LogClickCount(this,336);">Unity</a>
<a title="Splashtop" href="http://www.csdn.net/tag/splashtop" target="_blank" onclick="LogClickCount(this,336);">Splashtop</a>
<a title="UML" href="http://www.csdn.net/tag/uml" target="_blank" onclick="LogClickCount(this,336);">UML</a>
<a title="components" href="http://www.csdn.net/tag/components" target="_blank" onclick="LogClickCount(this,336);">components</a>
<a title="Windows Mobile" href="http://www.csdn.net/tag/windowsmobile" target="_blank" onclick="LogClickCount(this,336);">Windows Mobile</a>
<a title="Rails" href="http://www.csdn.net/tag/rails" target="_blank" onclick="LogClickCount(this,336);">Rails</a>
<a title="QEMU" href="http://www.csdn.net/tag/qemu" target="_blank" onclick="LogClickCount(this,336);">QEMU</a>
<a title="KDE" href="http://www.csdn.net/tag/kde" target="_blank" onclick="LogClickCount(this,336);">KDE</a>
<a title="Cassandra" href="http://www.csdn.net/tag/cassandra" target="_blank" onclick="LogClickCount(this,336);">Cassandra</a>
<a title="CloudStack" href="http://www.csdn.net/tag/cloudstack" target="_blank" onclick="LogClickCount(this,336);">CloudStack</a>
<a title="FTC" href="http://www.csdn.net/tag/ftc" target="_blank" onclick="LogClickCount(this,336);">FTC</a>
<a title="coremail" href="http://www.csdn.net/tag/coremail" target="_blank" onclick="LogClickCount(this,336);">coremail</a>
<a title="OPhone " href="http://www.csdn.net/tag/ophone " target="_blank" onclick="LogClickCount(this,336);">OPhone </a>
<a title="CouchBase" href="http://www.csdn.net/tag/couchbase" target="_blank" onclick="LogClickCount(this,336);">CouchBase</a>
<a title="云计算" href="http://www.csdn.net/tag/云计算" target="_blank" onclick="LogClickCount(this,336);">云计算</a>
<a title="iOS6" href="http://www.csdn.net/tag/iOS6" target="_blank" onclick="LogClickCount(this,336);">iOS6</a>
<a title="Rackspace " href="http://www.csdn.net/tag/rackspace " target="_blank" onclick="LogClickCount(this,336);">Rackspace </a>
<a title="Web App" href="http://www.csdn.net/tag/webapp" target="_blank" onclick="LogClickCount(this,336);">Web App</a>
<a title="SpringSide" href="http://www.csdn.net/tag/springside" target="_blank" onclick="LogClickCount(this,336);">SpringSide</a>
<a title="Maemo" href="http://www.csdn.net/tag/maemo" target="_blank" onclick="LogClickCount(this,336);">Maemo</a>
<a title="Compuware" href="http://www.csdn.net/tag/compuware" target="_blank" onclick="LogClickCount(this,336);">Compuware</a>
<a title="大数据" href="http://www.csdn.net/tag/大数据" target="_blank" onclick="LogClickCount(this,336);">大数据</a>
<a title="aptech" href="http://www.csdn.net/tag/aptech" target="_blank" onclick="LogClickCount(this,336);">aptech</a>
<a title="Perl" href="http://www.csdn.net/tag/perl" target="_blank" onclick="LogClickCount(this,336);">Perl</a>
<a title="Tornado" href="http://www.csdn.net/tag/tornado" target="_blank" onclick="LogClickCount(this,336);">Tornado</a>
<a title="Ruby" href="http://www.csdn.net/tag/ruby" target="_blank" onclick="LogClickCount(this,336);">Ruby</a>
<a title="Hibernate" href="http://www.csdn.net/hibernate" target="_blank" onclick="LogClickCount(this,336);">Hibernate</a>
<a title="ThinkPHP" href="http://www.csdn.net/tag/thinkphp" target="_blank" onclick="LogClickCount(this,336);">ThinkPHP</a>
<a title="Spark" href="http://www.csdn.net/tag/spark" target="_blank" onclick="LogClickCount(this,336);">Spark</a>
<a title="HBase" href="http://www.csdn.net/tag/hbase" target="_blank" onclick="LogClickCount(this,336);">HBase</a>
<a title="Pure" href="http://www.csdn.net/tag/pure" target="_blank" onclick="LogClickCount(this,336);">Pure</a>
<a title="Solr" href="http://www.csdn.net/tag/solr" target="_blank" onclick="LogClickCount(this,336);">Solr</a>
<a title="Angular" href="http://www.csdn.net/tag/angular" target="_blank" onclick="LogClickCount(this,336);">Angular</a>
<a title="Cloud Foundry" href="http://www.csdn.net/tag/cloudfoundry" target="_blank" onclick="LogClickCount(this,336);">Cloud Foundry</a>
<a title="Redis" href="http://www.csdn.net/tag/redis" target="_blank" onclick="LogClickCount(this,336);">Redis</a>
<a title="Scala" href="http://www.csdn.net/tag/scala" target="_blank" onclick="LogClickCount(this,336);">Scala</a>
<a title="Django" href="http://www.csdn.net/tag/django" target="_blank" onclick="LogClickCount(this,336);">Django</a>
<a title="Bootstrap" href="http://www.csdn.net/tag/bootstrap" target="_blank" onclick="LogClickCount(this,336);">Bootstrap</a>
    </div>
</div>

                    <div class="clear">
                    </div>
                </div>
            </div>
            <div id="side">
    <div class="side">
<div id="panel_Profile" class="panel">
<ul class="panel_head"><span>个人资料</span></ul>
<ul class="panel_body profile">
<div id="blog_userface">
    <a href="http://my.csdn.net/Luoshengyang" target="_blank">
    <img src="http://avatar.csdn.net/5/6/E/1_luoshengyang.jpg" title="访问我的空间" style="max-width:90%"/>
    </a>
    <br />
    <span><a href="http://my.csdn.net/Luoshengyang" class="user_name" target="_blank">Luoshengyang</a></span>
</div>
<div class="interact">
<a href="javascript:void(0);" class="attent" id="span_add_follow" title="[加关注]" onclick="_gaq.push(['_trackEvent','function', 'onclick', 'blog_articles_guanzhu'])"></a>
<a href="javascript:void(0);" class="letter" onclick="loginto(1)" title="[发私信]" onclick="_gaq.push(['_trackEvent','function', 'onclick', 'blog_articles_sixin'])"></a>
</div>
<div id="blog_medal">
        <div class="ico_expert" title="CSDN认证专家"></div>
</div>
<ul id="blog_rank">
    <li>访问：<span>3159517次</span></li>
    <li>积分：<span>16447分</span></li>
    <li>排名：<span>第129名</span></li>
</ul>
<ul id="blog_statistics">
    <li>原创：<span>100篇</span></li>
    <li>转载：<span>0篇</span></li>
    <li>译文：<span>0篇</span></li>
    <li>评论：<span>5212条</span></li>
</ul>
</ul>
</div>


<div id="custom_column_6567056" class="panel">
<ul class="panel_head"><span>博客公告</span></ul>
<ul class="panel_body">
<b><font color="red" size="2">本博客所有文章均为原创，欢迎交流，欢迎转载；转载请勿篡改内容，并且注明出处，禁止用于商业目的，谢谢！</font></b>
</ul>
</div><div id="custom_column_21664874" class="panel">
<ul class="panel_head"><span>图书信息</span></ul>
<ul class="panel_body">
<font color="red"><b>书名：</b></font>
<p>《Android系统源代码情景分析》</p>

<p><a href="http://wenku.it168.com/d_000574719.shtml" target="_blank">试读请点击</a></p>

<p><font color="red"><b>出版社：</b></font></p>
<p>电子工业出版社</p>

<p><font color="red"><b>网店：</b></font></p>

<p>1. <a href="http://product.dangdang.com/product.aspx?product_id=22884086" target="_blank">当当网（满100减20，满200减50）</a></p><p></p>

<p>2. <a href="http://book.360buy.com/11104739.html" target="_blank">京东网（满99减20）</a></p><p></p>

<p>3. <a href="http://www.amazon.cn/Android%E7%B3%BB%E7%BB%9F%E6%BA%90%E4%BB%A3%E7%A0%81%E6%83%85%E6%99%AF%E5%88%86%E6%9E%90-%E7%BD%97%E5%8D%87%E9%98%B3/dp/B009OLU8EE" target="_blank">亚马逊网（满100减20，满200减50）</a></p><p></p>

<p>4. <a href="http://product.china-pub.com/3684413" target="_blank">互动出版网</a></p><p></p>

<p>5. <a href="http://www.suning.com/emall/prd_10052_22001_-7_3435777_.html" target="_blank">苏宁易购网</a></p><p></p>

<p><a href="http://s.etao.com/search?spm=1002.8.1.1386.g76Rk3&amp;q=Android%CF%B5%CD%B3%D4%B4%B4%FA%C2%EB%C7%E9%BE%B0%B7%D6%CE%F6&amp;style=list&amp;initiative_id=etao_20121011&amp;pn=1&amp;sort=sale-desc" target="_blank">比一比谁更实惠</a></p>

<p><font color="red"><b>号外：</b></font></p>

<p>本书繁体版已经成功输出到台湾</p>

<p></p>
</ul>
</div><div id="custom_column_21603386" class="panel">
<ul class="panel_head"><span>联系方式</span></ul>
<ul class="panel_body">
<font color="red"><b>新浪微博：</b></font>
<p><a href="http://weibo.com/shengyangluo" target="_blank"><font color="red"><b>http://weibo.com/shengyangluo</b></font></a></p><p></p>

<font color="red"><b>QQ交流群：</b></font>
<p><b><font color="red">130112760</font></b>（1000人群，已满）</p>
<p><b><font color="red">248749286</font></b>（1000人群，已满）</p>
<p><b><font color="red">204155322</font></b>（500人群，未满）</p>
<p><b><font color="red">278558417</font></b>（500人群，已满）</p>
<p><b><font color="red">303165655</font></b>（500人群，已满）</p>
<p>PS：请勿同时加入多个群，一经发现，永久封号，谢谢！</p>
</ul>
</div><div id="panel_Category" class="panel">
    <ul class="panel_head"><span>博客专栏</span></ul>
    <ul class="panel_body" id="sp_column">
    <table cellpadding="0" cellspacing="0"><tr>
    <td style="padding:10px 10px 0 0;">
    <a href="http://blog.csdn.net/column/details/androidluo.html" target="_blank"><img src="http://avatar.csdn.net/blogpic/20111107095438958.jpg" style="width:75px;height:75px;" /></a>
    </td>
    <td style="padding:10px 0; vertical-align:top;">
    <a href="http://blog.csdn.net/column/details/androidluo.html" target="_blank">老罗的Android之旅</a>
    <p>文章：100篇</p>
    <span>阅读：3163336</span>
    </td>
    </tr></table>
    </ul>
</div><div id="hotarticls" class="panel">
<ul class="panel_head"><span>阅读排行</span></ul>
<ul class="panel_body itemlist">
<li>
<a href="/luoshengyang/article/details/6559955" title="在Ubuntu上下载、编译和安装Android最新源代码">在Ubuntu上下载、编译和安装Android最新源代码</a><span>(109317)</span>
</li>
<li>
<a href="/luoshengyang/article/details/6618363" title="Android进程间通信（IPC）机制Binder简要介绍和学习计划">Android进程间通信（IPC）机制Binder简要介绍和学习计划</a><span>(95185)</span>
</li>
<li>
<a href="/luoshengyang/article/details/6689748" title="Android应用程序启动过程源代码分析">Android应用程序启动过程源代码分析</a><span>(80750)</span>
</li>
<li>
<a href="/luoshengyang/article/details/6568411" title="在Ubuntu上为Android系统编写Linux内核驱动程序">在Ubuntu上为Android系统编写Linux内核驱动程序</a><span>(78561)</span>
</li>
<li>
<a href="/luoshengyang/article/details/8923485" title="那两年炼就的Android内功修养">那两年炼就的Android内功修养</a><span>(76460)</span>
</li>
<li>
<a href="/luoshengyang/article/details/6567257" title="Android硬件抽象层（HAL）概要介绍和学习计划">Android硬件抽象层（HAL）概要介绍和学习计划</a><span>(72469)</span>
</li>
<li>
<a href="/luoshengyang/article/details/6564592" title="在Ubuntu上下载、编译和安装Android最新内核源代码（Linux Kernel）">在Ubuntu上下载、编译和安装Android最新内核源代码（Linux Kernel）</a><span>(66668)</span>
</li>
<li>
<a href="/luoshengyang/article/details/6557518" title="Android学习启动篇">Android学习启动篇</a><span>(58980)</span>
</li>
<li>
<a href="/luoshengyang/article/details/6566662" title="如何单独编译Android源代码中的模块">如何单独编译Android源代码中的模块</a><span>(57960)</span>
</li>
<li>
<a href="/luoshengyang/article/details/6575988" title="在Ubuntu为Android硬件抽象层（HAL）模块编写JNI方法提供Java访问硬件服务接口">在Ubuntu为Android硬件抽象层（HAL）模块编写JNI方法提供Java访问硬件服务接口</a><span>(56692)</span>
</li>
</ul>
</div>
<div id="hotarticls2" class="panel">
<ul class="panel_head"><span>评论排行</span></ul>
<ul class="panel_body itemlist">
<li>
<a href="/luoshengyang/article/details/6689748" title="Android应用程序启动过程源代码分析">Android应用程序启动过程源代码分析</a><span>(322)</span>
</li>
<li>
<a href="/luoshengyang/article/details/6559955" title="在Ubuntu上下载、编译和安装Android最新源代码">在Ubuntu上下载、编译和安装Android最新源代码</a><span>(238)</span>
</li>
<li>
<a href="/luoshengyang/article/details/8116866" title="《Android系统源代码情景分析》一书勘误">《Android系统源代码情景分析》一书勘误</a><span>(208)</span>
</li>
<li>
<a href="/luoshengyang/article/details/6882903" title="Android应用程序键盘（Keyboard）消息处理机制分析">Android应用程序键盘（Keyboard）消息处理机制分析</a><span>(182)</span>
</li>
<li>
<a href="/luoshengyang/article/details/8923485" title="那两年炼就的Android内功修养">那两年炼就的Android内功修养</a><span>(181)</span>
</li>
<li>
<a href="/luoshengyang/article/details/6580267" title="在Ubuntu上为Android系统内置Java应用程序测试Application Frameworks层的硬件服务">在Ubuntu上为Android系统内置Java应用程序测试Application Frameworks层的硬件服务</a><span>(170)</span>
</li>
<li>
<a href="/luoshengyang/article/details/7409491" title="Android博客文章整理">Android博客文章整理</a><span>(167)</span>
</li>
<li>
<a href="/luoshengyang/article/details/6568411" title="在Ubuntu上为Android系统编写Linux内核驱动程序">在Ubuntu上为Android系统编写Linux内核驱动程序</a><span>(151)</span>
</li>
<li>
<a href="/luoshengyang/article/details/8452527" title="2012年的Android之旅：梦想、学习、坚持、自信、淡定">2012年的Android之旅：梦想、学习、坚持、自信、淡定</a><span>(139)</span>
</li>
<li>
<a href="/luoshengyang/article/details/6564592" title="在Ubuntu上下载、编译和安装Android最新内核源代码（Linux Kernel）">在Ubuntu上下载、编译和安装Android最新内核源代码（Linux Kernel）</a><span>(136)</span>
</li>
</ul>
</div>
<div id="newcomments" class="panel">
<ul class="panel_head"><span>最新评论</span></ul>
<ul class="panel_body itemlist">
    <li>
    <a href="/Luoshengyang/article/details/6568411#comments">在Ubuntu上为Android系统编写Linux内核驱动程序</a>
    <p style="margin:0px;"><a href="/HuiyuYang_fish" class="user_name">HuiyuYang_fish</a>:
期待实验~
    </p>
    </li>
    <li>
    <a href="/Luoshengyang/article/details/6557518#comments">Android学习启动篇</a>
    <p style="margin:0px;"><a href="/HuiyuYang_fish" class="user_name">HuiyuYang_fish</a>:
貌似我也要开始android的初步涉猎了~
    </p>
    </li>
    <li>
    <a href="/Luoshengyang/article/details/12957169#comments">《老罗的Android之旅》导读PPT</a>
    <p style="margin:0px;"><a href="/mianju23" class="user_name">mianju23</a>:
牛人
    </p>
    </li>
    <li>
    <a href="/Luoshengyang/article/details/8452527#comments">2012年的Android之旅：梦想、学习、坚持、自信、淡定</a>
    <p style="margin:0px;"><a href="/wuxiaoming1733" class="user_name">wuxiaoming1733</a>:
顶楼主
    </p>
    </li>
    <li>
    <a href="/Luoshengyang/article/details/6737352#comments">Android应用程序注册广播接收器（registerReceiver）的过程分析</a>
    <p style="margin:0px;"><a href="/wuxiaoming1733" class="user_name">wuxiaoming1733</a>:
罗大神你好，我这边还没明白，怎么自己用代码，实现androidmanifest.xml里静态注册系统...
    </p>
    </li>
    <li>
    <a href="/Luoshengyang/article/details/6642463#comments">Android系统进程间通信Binder机制在应用程序框架层的Java接口源代码分析</a>
    <p style="margin:0px;"><a href="/zqz19891031" class="user_name">zqz19891031</a>:
博主您好，看了你的博客，收获颇多！有一个问题想请教：最近在看Android的Binder实现，看到B...
    </p>
    </li>
    <li>
    <a href="/Luoshengyang/article/details/8923485#comments">那两年炼就的Android内功修养</a>
    <p style="margin:0px;"><a href="/xin128888" class="user_name">xin128888</a>:
老罗，有问题能否指导下。目前我想学习驱动相关知识，但是不知道要看哪本入门书籍合适，目标主要是快速入门...
    </p>
    </li>
    <li>
    <a href="/Luoshengyang/article/details/19023609#comments">Android源代码编译命令m/mm/mmm/make分析</a>
    <p style="margin:0px;"><a href="/soledadzz" class="user_name">soledadzz</a>:
您的文章已被推荐到CSDN首页，感谢您的分享。
    </p>
    </li>
    <li>
    <a href="/Luoshengyang/article/details/19023609#comments">Android源代码编译命令m/mm/mmm/make分析</a>
    <p style="margin:0px;"><a href="/u013725065" class="user_name">u013725065</a>:

    </p>
    </li>
    <li>
    <a href="/Luoshengyang/article/details/19023609#comments">Android源代码编译命令m/mm/mmm/make分析</a>
    <p style="margin:0px;"><a href="/u013725065" class="user_name">u013725065</a>:

    </p>
    </li>
</ul>
</div>
    </div>
    <div class="clear">
    </div>
</div>

            <div class="clear">
            </div>
        </div>
        

<script type="text/javascript" src="http://static.blog.csdn.net/scripts/newblog.min.js"></script>
<script type="text/javascript" src="http://medal.blog.csdn.net/showblogmedal.ashx?blogid=1134701"></script>
<script type="text/javascript">
    document.write('<script type="text/javascript" src="http://csdnimg.cn/pubfooter/js/publib_footer.js?' + Math.floor(new Date() / 120000).toString(36) + '="></' + 'script>');
</script>
    <script type="text/javascript" src="http://passport.csdn.net/content/loginbox/login.js"></script>
<script type="text/javascript">document.write("<img src=http://counter.csdn.net/pv.aspx?id=24 border=0 width=0 height=0>");</script>
<script type="text/javascript" src="http://www.csdn.net/ui/scripts/Csdn/counter.js"></script>
<script type="text/javascript" src="http://ad.csdn.net/scripts/ad-blog.js"></script>
<script type="text/javascript" src="http://zz.csdn.net/js/count.js"></script>
<script type="text/javascript">
    $(function () {
        function __get_code_toolbar(snippet_id) {
            return $("<a href='https://code.csdn.net/snippets/"
                    + snippet_id
                    + "' target='_blank' title='在CODE上查看代码片' style='text-indent:0;'><img src='https://code.csdn.net/assets/CODE_ico.png' width=12 height=12 alt='在CODE上查看代码片' style='position:relative;top:1px;left:2px;'/></a>"
                    + "<a href='https://code.csdn.net/snippets/"
                    + snippet_id
                    + "/fork' target='_blank' title='派生到我的代码片'  style='text-indent:0;'><img src='https://code.csdn.net/assets/ico_fork.svg' width=12 height=12 alt='派生到我的代码片' style='position:relative;top:2px;left:2px;'/></a>");
        }
        
        $("[code_snippet_id]").each(function () {
            __s_id = $(this).attr("code_snippet_id");
            if (__s_id != null && __s_id != "" && __s_id != 0 && parseInt(__s_id) > 70020) {
                __code_tool = __get_code_toolbar(__s_id);
                $(this).prev().find(".tools").append(__code_tool);
            }
        });
    });
</script>

    </div>
      <!--new top-->
    
    <script id="csdn-toolbar-id" btnId="header_notice_num" wrapId="note1" count="5" subCount="5" type="text/javascript" src="http://static.csdn.net/public/common/toolbar/js/toolbar.js"></script>     <!--new top-->
</body>
</html>
